"""
环境配置管理工具
提供环境切换、配置验证、配置导出等功能
"""
import os
import sys
from typing import Dict, Any, Optional
from pathlib import Path
import json

from app.core.config import get_settings, config_map, BaseConfig


class ConfigManager:
    """配置管理器"""
    
    def __init__(self):
        self.current_env = os.getenv("ENVIRONMENT", "development").lower()
        self.project_root = Path(__file__).parent.parent.parent
    
    def get_current_environment(self) -> str:
        """获取当前环境"""
        return self.current_env
    
    def get_available_environments(self) -> list[str]:
        """获取可用的环境列表"""
        return list(config_map.keys())
    
    def switch_environment(self, env: str) -> bool:
        """切换环境"""
        if env not in config_map:
            print(f"❌ 错误：环境 '{env}' 不存在。可用环境：{list(config_map.keys())}")
            return False
        
        # 设置环境变量
        os.environ["ENVIRONMENT"] = env
        self.current_env = env
        
        print(f"✅ 已切换到 {env} 环境")
        return True
    
    def validate_config(self, env: Optional[str] = None) -> Dict[str, Any]:
        """验证配置"""
        target_env = env or self.current_env
        
        if target_env not in config_map:
            return {"valid": False, "error": f"环境 '{target_env}' 不存在"}
        
        try:
            # 临时切换环境进行验证
            original_env = os.getenv("ENVIRONMENT")
            os.environ["ENVIRONMENT"] = target_env
            
            # 重新加载配置
            from app.core.config import get_settings
            get_settings.cache_clear()
            settings = get_settings()
            
            # 恢复原环境
            if original_env:
                os.environ["ENVIRONMENT"] = original_env
            else:
                os.environ.pop("ENVIRONMENT", None)
            
            return {
                "valid": True,
                "environment": target_env,
                "config_class": settings.__class__.__name__,
                "debug": settings.debug,
                "database_url": settings.database_url[:50] + "..." if len(settings.database_url) > 50 else settings.database_url,
                "redis_url": settings.redis_url,
                "log_level": settings.log_level
            }
            
        except Exception as e:
            return {"valid": False, "error": str(e)}
    
    def export_config(self, env: Optional[str] = None, include_sensitive: bool = False) -> Dict[str, Any]:
        """导出配置信息"""
        target_env = env or self.current_env
        
        if target_env not in config_map:
            return {"error": f"环境 '{target_env}' 不存在"}
        
        try:
            # 临时切换环境
            original_env = os.getenv("ENVIRONMENT")
            os.environ["ENVIRONMENT"] = target_env
            
            # 重新加载配置
            from app.core.config import get_settings
            get_settings.cache_clear()
            settings = get_settings()
            
            # 恢复原环境
            if original_env:
                os.environ["ENVIRONMENT"] = original_env
            else:
                os.environ.pop("ENVIRONMENT", None)
            
            # 导出配置
            config_dict = settings.dict()
            
            # 敏感信息处理
            sensitive_keys = ['secret_key', 'database_url', 'redis_url', 'smtp_password']
            if not include_sensitive:
                for key in sensitive_keys:
                    if key in config_dict and config_dict[key]:
                        config_dict[key] = "***HIDDEN***"
            
            return {
                "environment": target_env,
                "config_class": settings.__class__.__name__,
                "config": config_dict
            }
            
        except Exception as e:
            return {"error": str(e)}
    
    def check_env_files(self) -> Dict[str, Any]:
        """检查环境配置文件是否存在"""
        result = {"available_files": {}, "missing_files": []}
        
        for env in config_map.keys():
            env_file = self.project_root / f".env.{env}"
            if env_file.exists():
                result["available_files"][env] = str(env_file)
            else:
                result["missing_files"].append(env)
        
        return result
    
    def create_sample_env_file(self, env: str) -> bool:
        """创建示例环境配置文件"""
        if env not in config_map:
            print(f"❌ 环境 '{env}' 不存在")
            return False
        
        env_file = self.project_root / f".env.{env}.example"
        
        try:
            # 获取该环境的默认配置
            config_class = config_map[env]
            default_config = config_class()
            
            # 生成示例配置文件内容
            content = f"# {env.upper()} 环境配置示例文件\n"
            content += f"# 复制此文件为 .env.{env} 并修改相应的配置值\n\n"
            content += f"ENVIRONMENT={env}\n\n"
            
            # 分组配置项
            groups = {
                "应用配置": ["app_name", "app_version", "debug", "host", "port"],
                "数据库配置": ["database_url", "database_echo", "database_pool_size", "database_max_overflow"],
                "JWT配置": ["secret_key", "algorithm", "access_token_expire_minutes", "refresh_token_expire_days"],
                "Redis配置": ["redis_url", "redis_password", "redis_db", "redis_max_connections"],
                "日志配置": ["log_level", "log_file", "log_max_size", "log_backup_count"],
                "CORS配置": ["cors_origins", "cors_allow_credentials", "cors_allow_methods", "cors_allow_headers"],
                "API配置": ["api_v1_prefix", "docs_url", "redoc_url", "openapi_url"],
                "文件上传配置": ["upload_dir", "max_file_size", "allowed_file_types"],
                "调度器配置": ["scheduler_enabled", "scheduler_timezone", "scheduler_max_workers"],
                "监控配置": ["metrics_enabled", "metrics_path", "health_check_path"],
                "邮件配置": ["smtp_server", "smtp_port", "smtp_username", "smtp_password", "smtp_tls", "mail_from"]
            }
            
            for group_name, keys in groups.items():
                content += f"# {group_name}\n"
                for key in keys:
                    if hasattr(default_config, key):
                        value = getattr(default_config, key)
                        if value is None:
                            content += f"{key.upper()}=\n"
                        elif isinstance(value, str):
                            content += f"{key.upper()}={value}\n"
                        elif isinstance(value, bool):
                            content += f"{key.upper()}={str(value).lower()}\n"
                        elif isinstance(value, (int, float)):
                            content += f"{key.upper()}={value}\n"
                        elif isinstance(value, list):
                            content += f"{key.upper()}={json.dumps(value)}\n"
                        else:
                            content += f"{key.upper()}={value}\n"
                content += "\n"
            
            # 写入文件
            with open(env_file, 'w', encoding='utf-8') as f:
                f.write(content)
            
            print(f"✅ 已创建示例配置文件：{env_file}")
            return True
            
        except Exception as e:
            print(f"❌ 创建示例配置文件失败：{e}")
            return False
    
    def get_config_diff(self, env1: str, env2: str) -> Dict[str, Any]:
        """比较两个环境的配置差异"""
        if env1 not in config_map or env2 not in config_map:
            return {"error": "一个或多个环境不存在"}
        
        try:
            # 获取两个环境的配置
            original_env = os.getenv("ENVIRONMENT")
            
            # 获取第一个环境的配置
            os.environ["ENVIRONMENT"] = env1
            from app.core.config import get_settings
            get_settings.cache_clear()
            config1 = get_settings().dict()
            
            # 获取第二个环境的配置
            os.environ["ENVIRONMENT"] = env2
            get_settings.cache_clear()
            config2 = get_settings().dict()
            
            # 恢复原环境
            if original_env:
                os.environ["ENVIRONMENT"] = original_env
            else:
                os.environ.pop("ENVIRONMENT", None)
            
            # 比较差异
            differences = {}
            all_keys = set(config1.keys()) | set(config2.keys())
            
            for key in all_keys:
                val1 = config1.get(key, "NOT_SET")
                val2 = config2.get(key, "NOT_SET")
                
                if val1 != val2:
                    differences[key] = {
                        env1: val1,
                        env2: val2
                    }
            
            return {
                "env1": env1,
                "env2": env2,
                "differences": differences,
                "total_differences": len(differences)
            }
            
        except Exception as e:
            return {"error": str(e)}


# 全局配置管理器实例
config_manager = ConfigManager()


def print_config_info():
    """打印当前配置信息"""
    manager = config_manager
    current_env = manager.get_current_environment()
    
    print(f"\n🔧 环境配置信息")
    print(f"{'='*50}")
    print(f"当前环境: {current_env}")
    print(f"可用环境: {', '.join(manager.get_available_environments())}")
    
    # 验证当前配置
    validation = manager.validate_config()
    if validation["valid"]:
        print(f"配置状态: ✅ 有效")
        print(f"配置类: {validation['config_class']}")
        print(f"调试模式: {validation['debug']}")
        print(f"数据库: {validation['database_url']}")
        print(f"Redis: {validation['redis_url']}")
        print(f"日志级别: {validation['log_level']}")
    else:
        print(f"配置状态: ❌ 无效 - {validation['error']}")
    
    # 检查环境文件
    env_files = manager.check_env_files()
    print(f"\n📁 环境配置文件:")
    for env, path in env_files["available_files"].items():
        print(f"  ✅ {env}: {path}")
    for env in env_files["missing_files"]:
        print(f"  ❌ {env}: 文件不存在")
    
    print(f"{'='*50}\n")


if __name__ == "__main__":
    # 命令行工具
    if len(sys.argv) > 1:
        command = sys.argv[1].lower()
        
        if command == "info":
            print_config_info()
        
        elif command == "switch" and len(sys.argv) > 2:
            env = sys.argv[2].lower()
            config_manager.switch_environment(env)
            print_config_info()
        
        elif command == "validate":
            env = sys.argv[2].lower() if len(sys.argv) > 2 else None
            result = config_manager.validate_config(env)
            print(json.dumps(result, indent=2, ensure_ascii=False))
        
        elif command == "export":
            env = sys.argv[2].lower() if len(sys.argv) > 2 else None
            include_sensitive = "--include-sensitive" in sys.argv
            result = config_manager.export_config(env, include_sensitive)
            print(json.dumps(result, indent=2, ensure_ascii=False))
        
        elif command == "diff" and len(sys.argv) > 3:
            env1, env2 = sys.argv[2].lower(), sys.argv[3].lower()
            result = config_manager.get_config_diff(env1, env2)
            print(json.dumps(result, indent=2, ensure_ascii=False))
        
        elif command == "create-sample" and len(sys.argv) > 2:
            env = sys.argv[2].lower()
            config_manager.create_sample_env_file(env)
        
        else:
            print("用法:")
            print("  python -m app.core.config_manager info                    # 显示配置信息")
            print("  python -m app.core.config_manager switch <env>            # 切换环境")
            print("  python -m app.core.config_manager validate [env]          # 验证配置")
            print("  python -m app.core.config_manager export [env]            # 导出配置")
            print("  python -m app.core.config_manager diff <env1> <env2>      # 比较配置")
            print("  python -m app.core.config_manager create-sample <env>     # 创建示例配置")
    else:
        print_config_info()